package za.co.chris.nzb;

import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.SocketException;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.atomic.AtomicLong;

import org.apache.commons.net.nntp.NNTPClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class NNTPConnection {

	private Logger logger = LoggerFactory.getLogger(NNTPConnection.class);
	private NNTPClient client;

	private BufferedReader reader;
	private char[] buffer = new char[1024];
	private AtomicLong progerss;
	private DownloadThread thread;

	public NNTPConnection(String group, String url, int port) throws SocketException, IOException {
		client = new NNTPClient();
		client.connect(url, port);
	}

	public FutureTask<Boolean> getBody(String group, String articleId, String downloadName) throws IOException {
		progerss = new AtomicLong();
		client.selectNewsgroup(group);
		reader = (BufferedReader) client.retrieveArticleBody(articleId);
		thread = new DownloadThread(reader, downloadName, progerss, logger);
		FutureTask<Boolean> downloader = new FutureTask<>(thread);
		return downloader;
	}
}

class DownloadThread implements Callable<Boolean> {
	Logger logger;
	private BufferedReader reader;
	private FileWriter writer;
	private AtomicLong progerss;
	private boolean successful = true;

	public DownloadThread(BufferedReader reader, String downloadName, AtomicLong progerss, Logger logger) throws IOException {
		this.reader = reader;
		writer = new FileWriter(downloadName);
		this.progerss = progerss;
		this.logger = logger;
	}

	@Override
	public Boolean call() throws Exception {
		char reade;
		try {
			while ((reade = (char) reader.read()) != -1) {
				this.progerss.incrementAndGet();
				writer.append(reade);
			}
		} catch (IOException e) {
			this.logger.error("Error while reading or writing segment", e);
			successful = false;
		} finally {
			try {
				reader.close();
				writer.flush();
				writer.close();
			} catch (IOException e) {
				this.logger.error("Error closing the reader or writer", e);
			}
		}
		return successful;
	}
}
